/*
*  Copyright 2019-2020 Zheng Jie
*
*  Licensed under the Apache License, Version 2.0 (the "License");
*  you may not use this file except in compliance with the License.
*  You may obtain a copy of the License at
*
*  http://www.apache.org/licenses/LICENSE-2.0
*
*  Unless required by applicable law or agreed to in writing, software
*  distributed under the License is distributed on an "AS IS" BASIS,
*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*  See the License for the specific language governing permissions and
*  limitations under the License.
*/
package me.zhengjie.modules.insurance.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.IdcardUtil;
import me.zhengjie.exception.BadRequestException;
import me.zhengjie.modules.insurance.domain.InsuredUser;
import me.zhengjie.modules.insurance.handler.InsuredUserUploadHandler;
import me.zhengjie.modules.insurance.pojo.MatchingSiteRequest;
import me.zhengjie.modules.system.service.DeptService;
import me.zhengjie.modules.system.service.UserService;
import me.zhengjie.utils.*;
import lombok.RequiredArgsConstructor;
import me.zhengjie.modules.insurance.repository.InsuredUserRepository;
import me.zhengjie.modules.insurance.service.InsuredUserService;
import me.zhengjie.modules.insurance.service.dto.InsuredUserDto;
import me.zhengjie.modules.insurance.service.dto.InsuredUserQueryCriteria;
import me.zhengjie.modules.insurance.service.mapstruct.InsuredUserMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.web.multipart.MultipartFile;

import java.sql.Timestamp;
import java.util.*;
import java.io.IOException;
import java.util.stream.Collectors;
import javax.servlet.http.HttpServletResponse;

/**
* @website https://el-admin.vip
* @description 服务实现
* @author HeHui
* @date 2021-12-26
**/
@Service
@RequiredArgsConstructor
public class InsuredUserServiceImpl implements InsuredUserService {

    private final InsuredUserRepository insuredUserRepository;
    private final InsuredUserMapper insuredUserMapper;
    private final me.zhengjie.modules.insurance.mapper.InsuredUserMapper userMapper;
    private final UserService userService;
    private final DeptService deptService;
    private final InsuredUserUploadHandler insuredUserUploadHandler;
    @Override
    public Map<String,Object> queryAll(InsuredUserQueryCriteria criteria, Pageable pageable){
        Page<InsuredUser> page = insuredUserRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable);
        Page<InsuredUserDto> userDtos = page.map(insuredUserMapper::toDto);
        return PageUtil.toPage(completionInfo(userDtos.getContent()), userDtos.getTotalElements());
    }


    /**
     * 完成信息
     *
     * @param dtos dto
     * @return {@link List}<{@link InsuredUserDto}>
     */
    private List<InsuredUserDto> completionInfo(List<InsuredUserDto> dtos) {
        if (CollUtil.isEmpty(dtos)) {
            return Collections.emptyList();
        }
        List<Long> userIds = new ArrayList<>();
        List<Long> createUserIds = dtos.stream().map(InsuredUserDto::getCreateUserId).distinct().collect(Collectors.toList());
        List<Long> updateUserIds = dtos.stream().map(InsuredUserDto::getLastUpdateId).distinct().collect(Collectors.toList());
        if (CollUtil.isNotEmpty(createUserIds)) {
            userIds.addAll(createUserIds);
        }
        if (CollUtil.isNotEmpty(updateUserIds)) {
            userIds.addAll(updateUserIds);
        }
        Map<Long, String> userNameMap = userService.getUserName(userIds.stream().distinct().collect(Collectors.toList()));

        dtos.forEach(v -> {
            v.setCreateUserName(userNameMap.get(v.getCreateUserId()));
            v.setLastUpdateName(userNameMap.get(v.getLastUpdateId()));
        });
        return dtos;
    }

    @Override
    public List<InsuredUserDto> queryAll(InsuredUserQueryCriteria criteria){
        return completionInfo(insuredUserMapper.toDto(insuredUserRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder))));
    }

    @Override
    @Transactional
    public InsuredUserDto findById(Long id) {
        InsuredUser insuredUser = insuredUserRepository.findById(id).orElseGet(InsuredUser::new);
        ValidationUtil.isNull(insuredUser.getId(),"InsuredUser","id",id);
        return insuredUserMapper.toDto(insuredUser);
    }

    /**
     * 存在生效中的保单
     *
     * @param userIdCard 用户id卡
     * @return boolean
     */
    @Override
    public boolean existsEffectPolicy(String userIdCard, Long notId) {
        Integer effectPolicy = userMapper.existsEffectPolicy(userIdCard, notId);
        return effectPolicy != null && effectPolicy > 0;
    }


    /**
     * 批量减员导出
     *
     * @param ids           id
     * @param currentUserId 当前用户id
     */
    @Override
    public void batchOut(List<Long> ids, long currentUserId) {
        if (CollUtil.isEmpty(ids)) {
            return;
        }
        userMapper.batchOut(ids, currentUserId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public InsuredUserDto create(InsuredUser resources) {
        if (!IdcardUtil.isValidCard(resources.getUserIdCard())) {
            throw new BadRequestException("身份证号码非法");
        }
        if (existsEffectPolicy(resources.getUserIdCard(), null)) {
            throw new BadRequestException("骑手存在生效中的保单！");
        }
//        List<InsuredUser> userNames = userMapper.findUserName(Arrays.asList(resources.getUserIdCard()));
//        if (CollUtil.isNotEmpty(userNames) && !userNames.contains(resources.getUserName())) {
//            throw new BadRequestException("骑手与历史人员名称不同!");
//        }
        Timestamp now = new Timestamp(System.currentTimeMillis());
        final Long currentUserId = SecurityUtils.getCurrentUserId();
        resources.setOwnerId(currentUserId);
        resources.setCreateTime(now);
        resources.setLastUpdateTime(now);
        resources.setCreateUserId(currentUserId);
        resources.setLastUpdateId(currentUserId);
        resources.setIsDeleted(0);
        resources.setPolicyStatus(1);
        resources.setPolicyStartTime(now);
        resources.setPolicyEntTime(null);
        userMapper.insertSelective(resources);

        return insuredUserMapper.toDto(resources);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(InsuredUser resources) {
//        InsuredUser insuredUser = insuredUserRepository.findById(resources.getId()).orElseGet(InsuredUser::new);
//        ValidationUtil.isNull( insuredUser.getId(),"InsuredUser","id",resources.getId());
//        insuredUser.copy(resources);
        if (!IdcardUtil.isValidCard(resources.getUserIdCard())) {
            throw new BadRequestException("身份证号码非法");
        }
        if (existsEffectPolicy(resources.getUserIdCard(), resources.getId())) {
            throw new BadRequestException("骑手存在生效中的保单！");
        }
        Timestamp now = new Timestamp(System.currentTimeMillis());
        final Long currentUserId = SecurityUtils.getCurrentUserId();

        InsuredUser update = new InsuredUser();
        update.setId(resources.getId());
        update.setLastUpdateTime(now);
        update.setLastUpdateId(currentUserId);
        update.setOwnerCompanyId(resources.getOwnerCompanyId());
        update.setUserName(resources.getUserName());
        update.setUserIdCard(resources.getUserIdCard());
        update.setUserMobile(resources.getUserMobile());
        update.setPolicyStartTime(resources.getPolicyStartTime());
        userMapper.updateByPrimaryKeySelective(update);

    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleteAll(Long[] ids, Long currentUserId) {
//        for (Long id : ids) {
//            insuredUserRepository.deleteById(id);
//        }
        userMapper.deletedInIds(ids, currentUserId);
    }

    @Override
    public void download(List<InsuredUserDto> all, HttpServletResponse response) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        List<Long> companyIds = all.stream().map(InsuredUserDto::getOwnerCompanyId).distinct().collect(Collectors.toList());
        Map<Long, String> companyMap = deptService.getDeptName(companyIds);
        for (InsuredUserDto insuredUser : all) {
            Map<String,Object> map = new LinkedHashMap<>();
            map.put("骑手姓名", insuredUser.getUserName());
            map.put("骑手身份证", insuredUser.getUserIdCard());
            map.put("录入人", insuredUser.getCreateUserName());
            map.put("所属公司", companyMap.get(insuredUser.getOwnerCompanyId()));
            map.put("保单生效时间", insuredUser.getPolicyStartTime());
            map.put("保单失效时间", insuredUser.getPolicyEntTime());
            map.put("在保状态", Objects.equals(insuredUser.getPolicyStatus(), 1) ? "在保" : "不在保");
            map.put("最后操作时间", insuredUser.getLastUpdateTime());
            map.put("操作人", insuredUser.getLastUpdateName());
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }


    /**
     * 上传
     *
     * @param file          文件
     * @param currentUserId 当前用户id
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void upload(MultipartFile file, long currentUserId) throws IOException {
        insuredUserUploadHandler.upload(file,currentUserId);
    }


    /**
     * 匹配所属公司
     *
     * @param request 请求
     * @return {@link Long}
     */
    @Override
    public Long matchingCompany(MatchingSiteRequest request) {
        return userMapper.matchingCompany(request);
    }

    /**
     * 匹配
     *
     * @param request 请求
     * @return {@link InsuredUserDto}
     */
    @Override
    public InsuredUserDto matching(MatchingSiteRequest request) {
        return insuredUserMapper.toDto(userMapper.matching(request));
    }
}